/**
 *dom操作封装，及相关工具类函数
 * by kevin.huang 2018-12-12
*/

var $body, DomUtils,_onNodeRemoveEventTimer;
function _getBody() {
    if (!$body) {
        $body = document.body;
        $B.DomUtils.css($body, { "position": "relative" });
    }
    return $body;
}
$B["getBody"] = _getBody;

var class2type = {},
    hasOwn = class2type.hasOwnProperty,
    toString = class2type.toString;

/***
 * 获取数据类型
 * ***/
function getDataType(obj) {
    var toString = Object.prototype.toString;
    var map = {
        '[object Boolean]': 'boolean',
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Function]': 'function',
        '[object Array]': 'array',
        '[object Date]': 'date',
        '[object RegExp]': 'regExp',
        '[object Undefined]': 'undefined',
        '[object Null]': 'null',
        '[object Object]': 'object'
    };
    if (obj instanceof Element) {
        return 'element';
    }
    return map[toString.call(obj)];
}
$B["getDataTypeFn"] = getDataType;

/****
 * 确保是数组
 * ******/
function ensureArray(data) {
    if (Array.isArray(data)) {
        return data;
    }
    return [data];
}
$B["ensureArrayFn"] = ensureArray;


function _isInArray(elem, arr, i) {
    var len;
    if (arr) {
        if (Array.prototype.indexOf) {
            return Array.prototype.indexOf.call(arr, elem, i);
        }
        len = arr.length;
        i = i ? i < 0 ? Math.max(0, len + i) : i : 0;
        for (; i < len; i++) {
            if (i in arr && arr[i] === elem) {
                return i;
            }
        }
    }
    return -1;
}
$B["isInArrayFn"] = _isInArray;

function _diyTrim(str) {
    var trimLeft = /^\s+/,
        trimRight = /\s+$/,
        rnotwhite = /\S/;
    if (rnotwhite.test("\xA0")) {
        trimLeft = /^[\s\xA0]+/;
        trimRight = /[\s\xA0]+$/;
    }
    return str == null ? "" : str.replace(trimLeft, "").replace(trimRight, "");
}

function _trim(str) {
    var r;
    if (String.prototype.trim) {
        r = str.trim();
    } else {
        r = _diyTrim(str);
    }
    r = r.replace(/\u200B/g, '');
    return r;
}

$B["trimFn"] = _trim;

// 变成驼峰
function camelFn(str) {
    return str.replace(/-(\w)/g, function (m0, m1) {
        return m1.toUpperCase();
    });
}
// 变成破折
function dashesFn(str) {
    return str.replace(/[A-Z]/g, function (m0) {
        return '-' + m0.toLowerCase();
    });
}
$B["camelFn"] = camelFn;
$B["dashesFn"] = dashesFn;

/**
 * 返回obj元素在array中的位置
 * @param {Array} array
 * @param {*} obj
 * @returns {number}
 * @private
 */
function _indexOf(array, obj) {
    if (Array.prototype.indexOf) {
        return Array.prototype.indexOf.call(array, obj);
    }
    for (var i = 0, j = array.length; i < j; i++) {
        if (array[i] === obj) {
            return i;
        }
    }
    return -1;
}
$B["indexOfArrayFn"] = _indexOf;
/**
 * 是否是数组
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isArray(object) {
    return Object.prototype.toString.call(object) === '[object Array]';
}
$B["isArrayFn"] = _isArray;
/**
 *是否是字符串
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isString(object) {
    return typeof object === 'string';
}
$B["isStringFn"] = _isString;
/**
 * 是否是数字
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isNumeric(object) {
    var ret = typeof object === 'number' && isFinite(object);
    if (!ret) {
        var regPos = /^\d+(\.\d+)?$/; //非负浮点数
        var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; //负浮点数
        if (regPos.test(object) && regNeg.test(object)) {
            ret = true;
        } else {
            ret = false;
        }
    }
    return ret;
}
$B["isNumericFn"] = _isNumeric;
/**
 * 是否是object对象
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isObject(object) {
    return typeof object === 'object';
}

function _isEmptyObject(object) {
    if (_isObject(object)) {
        return Object.keys(object).length === 0;
    }
    return false;
}
$B["isEmptyObjectFn"] = _isEmptyObject;

/**
 * 检查是否是函数
 * @param {*} object
 * @returns {boolean}
 * @private
 */
function _isFunction(object) {
    return typeof object === 'function';
}
$B["isFunctionFn"] = _isFunction;
/**
 * 检查是否是{}对象
 * @param object
 * @returns {*|boolean}
 * @private
 */
function _isLiteralObject(obj) {
    var key;
    if (!obj || typeof obj !== "object" || obj.nodeType) {
        return false;
    }
    try {
        if (obj.constructor &&
            !hasOwn.call(obj, "constructor") &&
            !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
            return false;
        }
    } catch (e) {
        return false;
    }
    for (key in obj) {
    }
    return key === undefined || hasOwn.call(obj, key);
    //return object && typeof object === "object" && Object.getPrototypeOf(object) === Object.getPrototypeOf({});
}
$B["isPlainObjectFn"] = _isLiteralObject;

/**
 * 检查是否是可迭代的元素
 * @param {Object} object
 * @returns {boolean}
 * @private
 */
function _isIterable(object) {
    if (object instanceof HTMLElement 
        || object instanceof Node || (typeof object === 'object' && object.nodeName && object.tagName)) {
        return false;
    }
    var r = _isLiteralObject(object) || _isArray(object) || (typeof object === 'object' && object !== null && object['length'] !== undefined);
    return r;
}
$B["isIterableFn"] = _isIterable;

/**
 * 深拷贝克隆一个对象
 * @param {Object} object
 * @private
 */
function _cloneObject(object) {
    var copy;
    var property;
    if (!_isObject(object) || object === null) {
        copy = object;
        return copy;
    }
    if (_isArray(object)) {
        copy = [];
        for (var i = 0, l = object.length; i < l; i++) {
            copy[i] = _cloneObject(object[i]);
        }
        return copy;
    }
    copy = {};
    for (property in object) {
        if (!object.hasOwnProperty(property)) {
            continue;
        }
        if (_isObject(object[property]) && object[property] !== null) {
            copy[property] = _cloneObject(object[property]);
        } else {
            copy[property] = object[property];
        }
    }
    return copy;
}
$B["cloneObjectFn"] = _cloneObject;



/****
 * 对象合并 ：将srcObj拷贝到destObj上
 * destObj:合并到的对象
 * srcObj：合并的来源对象
 * notOverride:不覆盖已经存在的key destObj, srcObj, notOverride
 * ******/
function _extendObjectFn() {
    var src, copyIsArray, copy, name, options, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;

    if (typeof target === "boolean") {
        deep = target;
        target = arguments[i] || {};
        i++;
    }

    if (typeof target !== "object" && typeof target !== "function") {
        target = {};
    }

    if (i === length) {
        target = this;
        i--;
    }

    for (; i < length; i++) {
        if ((options = arguments[i])) {
            for (name in options) {
                if (!options.hasOwnProperty(name)) {
                    continue;
                }
                src = target[name];
                copy = options[name];
                if (target === copy) {
                    continue;
                }
                if (deep && copy && (_isLiteralObject(copy) || (copyIsArray = _isArray(copy)))) {
                    if (copyIsArray) {
                        copyIsArray = false;
                        clone = src && _isArray(src) ? src : [];

                    } else {
                        clone = src && _isLiteralObject(src) ? src : {};
                    }
                    target[name] = _extendObjectFn(deep, clone, copy);

                } else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }
    return target;
}
$B["extendObjectFn"] = _extendObjectFn;

function needReplacePx(prop) {
    prop = prop.toLowerCase();
    if(prop.indexOf("border") >= 0 && prop.indexOf("width") < 0){
        return false;
    }
    if (prop.indexOf("width") > -1 || prop.indexOf("height") > -1 
    || prop.indexOf("top") > -1 || prop.indexOf("left") > -1 
    || prop.indexOf("padding") > -1 || prop.indexOf("margin") > -1
    ) {
        return true;
    }
    return false;
}
/**
 * 获取样式的style样式
 * @param element
 * @param prop
 * @returns {*}
 * @private
 */
function _getComputedStyle(element, prop) {
    var computedStyle;
    if (typeof window.getComputedStyle === 'function') { //normal browsers
        computedStyle = window.getComputedStyle(element);
    } else if (typeof document.currentStyle !== undefined) { //shitty browsers
        computedStyle = element.currentStyle;
    } else {
        computedStyle = element.style;
    }
    if (prop) {
        let value = computedStyle[prop];
        if (needReplacePx(prop)) {
            if(value.indexOf("px") > 0){
                value = parseFloat(value.replace("px", ""));
            }else if(/^-?\d+(.?\d+)?$/.test(value)){
                value = parseFloat(value);
            }
        }
        return value;
    } else {
        return computedStyle;
    }
}
$B["getComputedStyleFn"] = _getComputedStyle;
/**
 * 循环对象object
 * @param object
 * @param callback
 * @private
 */
function _each(object, callback) {
    var i, l;
    if (_isArray(object) || (typeof object === 'object' && object['length'] !== undefined)) {
        for (i = 0, l = object.length; i < l; i++) {
            callback.apply(object[i], [object[i], i]);
        }
        return;
    }
    if (_isLiteralObject(object)) {
        var keys = Object.keys(object);
        for (i = 0; i < keys.length; i++) {
            callback.apply(object[keys[i]], [object[keys[i]], keys[i]]);
        }
    }
}
$B["foreachFn"] = _each;

var _domReadyHandlers = [];
var _domLoadedHandlers = [];
var _isDomReady = false;
var _isDomLoaded = false;
var _animationLastTime;
/**这些属性不自动添加px单位**/
var CSSNumber = {
    "animationIterationCount": true,
    "animation-iteration-count": true,
    "columnCount": true,
    "column-count": true,
    "fillOpacity": true,
    "fill-opacity": true,
    "flexGrow": true,
    "flex-grow": true,
    "flexShrink": true,
    "flex-shrink": true,
    "opacity": true,
    "order": true,
    "orphans": true,
    "widows": true,
    "zIndex": true,
    "z-index": true,
    "zoom": true,
    "WebkitLineClamp":true,    
    "-webkit-line-clamp": true
};
var addListener = document.addEventListener ? 'addEventListener' : 'attachEvent';
var removeListener = document.removeEventListener ? 'removeEventListener' : 'detachEvent';
var eventPrefix = document.addEventListener ? '' : 'on';
var createEvent = document.createEvent ? 'createEvent' : 'createEventObject';
var dispatchEvent = document.dispatchEvent ? 'dispatchEvent' : 'fireEvent';
var vendors = ['-moz-', '-ms-', '-webkit-', '-o-', ''];
var cssMap = {
    "background-color":"backgroundColor",
    "z-index":"zIndex"  
};
var cssNameProperty = function (prop) { 
    var exp = /-([a-z0-9])/;
    while (exp.test(prop)) {
        prop = prop.replace(exp, RegExp.$1.toUpperCase());
    }
    return prop;
};
var requestAnimationFrame = window.requestAnimationFrame;
var cancelAnimationFrame = window.cancelAnimationFrame || window.cancelRequestAnimationFrame;
var div = document.createElement('div');
var style = _getComputedStyle(div);

//ie版本
var ie = (function () {
    var rv;
    if (navigator.appName === 'Microsoft Internet Explorer') {
        var ua = navigator.userAgent;
        var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
        if (re.exec(ua) != null) {
            rv = parseFloat(RegExp.$1);
        }
    }
    return rv;
}());

//transition detection
var transitionSupport = (function () {
    for (var i in vendors) {
        if (_isString(style[vendors[i] + 'transition'])) {
            return true;
        }
    }
    return false;
})();

//request animation pollyfill
if (!requestAnimationFrame || !cancelAnimationFrame) {
    for (var i = 0; i < vendors.length; i++) {
        var vendor = vendors[i];
        requestAnimationFrame = requestAnimationFrame || window[vendor + 'RequestAnimationFrame'];
        cancelAnimationFrame = cancelAnimationFrame || window[vendor + 'CancelAnimationFrame'] || window[vendor + 'CancelRequestAnimationFrame'];
    }
}

if (!requestAnimationFrame || !cancelAnimationFrame) {
    requestAnimationFrame = function (callback) {
        var currentTime = new Date().getTime();
        var timeToCall = Math.max(0, 16 - (currentTime - _animationLastTime));
        var id = window.setTimeout(function _requestAnimationFrameTimeout() {
            callback(currentTime + timeToCall);
        }, timeToCall);

        _animationLastTime = currentTime + timeToCall;
        return id;
    };

    cancelAnimationFrame = function (id) {
        window.clearTimeout(id);
    };
}

function _getOffset(elem) {
    var docElem, win,
        box = { top: 0, left: 0 },
        doc = elem && elem.ownerDocument;//当前文档
    if (!doc) {
        return;
    }
    docElem = doc.documentElement;
    if (typeof elem.getBoundingClientRect !== 'undefined') {//如果元素有getBoundingClientRect方法
        box = elem.getBoundingClientRect();//调用该方法
    }
    win = window;//如果是window就返回window，如果是document，返回document.defaultView
    return {
        //元素相对于视窗的距离+滚动距离-边框宽度
        top: box.top + win.pageYOffset - docElem.clientTop,
        left: box.left + win.pageXOffset - docElem.clientLeft
    };
}

var Mouse = {
    BUTTON_LEFT: 0,
    BUTTON_MIDDLE: 1,
    BUTTON_RIGHT: 2
};
//事件参数二次封装
function EventArgs(e) {
    this._e = e;
    if (!EventArgs.prototype.stopPropagation) {
        EventArgs.prototype.stopPropagation = function () {
            if (this._e.stopPropagation) {
                this._e.stopPropagation();
            } else {
                this._e.cancelBubble = true;
            }
        };
    }

    if (!EventArgs.prototype.stopPropagation) {
        EventArgs.prototype.preventDefault = function () {
            if (this._e.preventDefault) {
                this._e.preventDefault();
            } else {
                this._e.returnValue = false;
            }
        };
    }
    this.target = this._e.target || this._e.srcElement;
    this.ctrlKey = this._e.ctrlKey;
    this.shiftKey = this._e.shiftKey;
    this.altKey = this._e.altKey;
    this.layerY = this._e.layerY || this._e.offsetY;
    this.layerX = this._e.layerX || this._e.offsetX;
    this.x = this._e.x || this._e.clientX;
    this.y = this._e.y || this._e.clientY;
    this.pageX = this._e.pageX;
    this.pageY = this._e.pageY;
    this.keyCode = this._e.keyCode;
    this.name = this.type = this._e.type;
    this.path = this._e.path;    
    this.which = this._e.which;
    if (ie & ie < 9) {
        this.button = this._e.button === 1 ? Mouse.BUTTON_LEFT : (this._e.button === 4 ? Mouse.BUTTON_MIDDLE : Mouse.BUTTON_RIGHT);
    } else if (this._e.hasOwnProperty('which')) {
        this.button = this._e.which === 1 ? Mouse.BUTTON_LEFT : (this._e.which === 2 ? Mouse.BUTTON_MIDDLE : Mouse.BUTTON_RIGHT);
    } else {
        this.button = this._e.button;
    }
}
//dom事件机制封装
function commHandleEvent(event) {
    event = event || window.event;
    let handlers = this.events[event.type];
   
    if(_isEmptyObject(handlers)){        
        return;
    }
    var keys = Object.keys(handlers);
    let ret, handler,isEmpty = true;
    for (let i = 0; i < keys.length; i++) {
        handler = handlers[keys[i]];
        if(!handler){
            console.log("handler ex");
            continue; 
        }
        isEmpty = false;
        let ev = new EventArgs(event);
        ev.eventNamespace = handler.namespace;
        if (handler.params) {
            ev.params = handler.params;
        }
        let res;
        if (typeof handler.fn === "function") {
            ev.catpurer = this;
            res = handler.fn.call(this, ev);
        }
        if (typeof ret === "undefined" && typeof res !== "undefined") {
            ret = !res;
        }
    }
    if (ret) {//执行阻止冒泡
        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
        event.returnValue = false; 
    }
    if(isEmpty){
        console.log("not events clear el");
        delete this.events[event.type];
    }
}

var radioCheckboxHooks = {
    set: function (elem, value) {
        if (Array.isArray(value)) {
            return "";
        }
    },
    get: function (elem) {
        return elem.getAttribute("value") === null ? "on" : elem.value;
    }
};
let regName = /^(\w+)\[(.+)\]$/;
function getNameAndAttr(arg1){
    let ret = {name:arg1};
    if(regName.test(arg1)){
        let math = regName.exec(arg1);
        ret.name = math[1];
        ret.attr = math[2];
    }
    return ret;
}
var valHooks = {
    option: {
        get: function (elem) {
            var val = elem.getAttribute("value");
            return val != null ? _trim(val) : _trim(elem.innerText);
        },
        set: function (elem, value) {
        }
    },
    select: {
        get: function (elem) {
            var value, option,
                options = elem.options,
                index = elem.selectedIndex,//当前选中项 单选默认0，多选默认-1
                //如果是单选下拉框或者当前没有选中项，one为true
                one = elem.type === "select-one" || index < 0,
                values = one ? null : [],//one为true，则values为null，否则为[]
                max = one ? index + 1 : options.length,//单选最大为1,多选为options.length
                i = index < 0 ?
                    max :
                    one ? index : 0;
            for (; i < max; i++) {//遍历
                option = options[i];
                if ((option.selected || i === index) && (typeof option.disabled !== "undefined" ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || option.parentNode.nodeName.toLowerCase() !== "optgroup")) {
                    value = valHooks.option.get(option);
                    if (one) {//单选直接返回
                        return value;
                    }
                    values.push(value);//多选推入数组
                }
            }
            return values;//多选且没有没有默认项，不经过循环直接返回
        },
        set: function (elem, value) {
            var optionSet, option,
                options = elem.options,
                values = ensureArray(value),//转为数组,value可以是任何值 "a"=>["a"]
                i = options.length;//选项数量
            //遍历
            while (i--) {
                option = options[i];
                //如果当前选项的值在values数组中，selected为true，否则为false
                //可以用于设置多选的下拉单值
                /*用法：
                    <select name="" id="" class="slt" multiple>
                        <option value="a">aaa</option>
                        <option value="b">bbbb</option>
                        <option value="c">ccccc</option>
                    </select>
                    <script>
                        $('.slt').val(["a","c"]);
                    </script>
                 */
                if ((option.selected = _isInArray(option.value, values) >= 0)) {
                    optionSet = true;//标识
                }
            }

            // force browsers to behave consistently when non-matching value is set
            if (!optionSet) {
                elem.selectedIndex = -1;
            }
            return values;
        }
    },
    radio: radioCheckboxHooks,
    checkbox: radioCheckboxHooks
};
var DomApiObj = {
    /***
     * 对元素添加一个事件监听
     * element：元素
     * eventName ：事件名称,支持命名空间 namespac.click
     * listener:事件处理函数
     * params:额外的参数
     * **/
    addListener: function (eventName, listener, params) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.addListener.call(element[i], eventName, listener, params);
            }
            return this;
        }
        if (!element.eventIndex) {
            element.eventIndex = 1;
        } else {
            element.eventIndex++;
        }
        if (!element.events) {
            element.events = {};
        }
        var namespace = "", eventKey = element.eventIndex;
        if (eventName.indexOf(".") > 0) {
            let arr = eventName.split(".");
            namespace = arr[0];
            eventName = arr[1];
        }
        let handlers = element.events[eventName];
        if (!handlers) {
            handlers = {};
            handlers[eventKey] = {
                params: params,
                namespace: namespace,
                fn: listener
            };
            if (element.addEventListener) {
                element.addEventListener(eventName, commHandleEvent, false);
            } else {
                element["on" + eventName] = commHandleEvent;
            }
            listener.eventIndex = element.eventIndex;
            element.events[eventName] = handlers;
        } else {
            //避免重复添加
            if (listener.eventIndex) {
                if (handlers[listener.eventIndex] && handlers[listener.eventIndex].fn === listener) {                   
                    return DomUtils;
                }
            }
            handlers[eventKey] = {
                params: params,
                namespace: namespace,
                fn: listener
            };
            listener.eventIndex = element.eventIndex;
        }
        return this;
    },
    /***
     * 对元素移除事件
     * element：元素
     * eventName ：事件名称,支持命名空间 namespac.click
     * listener:事件处理函数
     * **/
    removeListener: function (eventName, listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.removeListener.call(element[i], eventName, listener);
            }
            return this;
        }
        if (element.events) {
            if (typeof eventName !== "string") {
                return;
            }
            var namespace;
            if (eventName.indexOf(".") > 0) {
                let arr = eventName.split(".");
                namespace = arr[0];
                eventName = arr[1];
            }
            if (eventName === "*") {
                listener = undefined;
            }
            if (element.events[eventName] || (eventName === "*" && namespace)) {
                if (namespace) {//如果存在命名空间
                    let allEventNames = Object.keys(element.events); // click 、mousedown、mouseup、change............   
                    let i, j, eventMap, eventKeys, eventKey, handler;
                    for (i = 0; i < allEventNames.length; i++) {
                        if (eventName === "*" || eventName === allEventNames[i] || typeof listener === "undefined") {
                            eventMap = element.events[allEventNames[i]];//click 、mousedown、mouseup、change事件集合
                            eventKeys = Object.keys(eventMap);//eventindex
                            for (j = 0; j < eventKeys.length; j++) {
                                eventKey = eventKeys[j];
                                handler = eventMap[eventKey];
                                if (handler.namespace !== "") { //事件是存在命名空间的
                                    if (handler.namespace === namespace) {
                                        if (typeof listener === "undefined") {
                                            if (eventName === "*" || eventName === allEventNames[i]) {//移除命名空间下的所有事件
                                                delete eventMap[eventKey];
                                            }
                                        } else {
                                            if (eventName === allEventNames[i] && (listener.eventIndex + '') === eventKey) {
                                                delete eventMap[eventKey];
                                            }
                                        }
                                    }
                                }
                            }
                            if (_isEmptyObject(eventMap)) {
                                delete element.events[allEventNames[i]];
                                element.removeEventListener(allEventNames[i], commHandleEvent);//移除通用处理
                            }
                        }
                    }
                } else {
                    if (listener) {
                        delete element.events[eventName][listener.eventIndex];
                    } else {
                        element.events[eventName] = {};
                    }
                }
            }
            if (!element.events[eventName] || Object.keys(element.events[eventName]).length === 0) {
                delete element.events[eventName];
                element.removeEventListener(eventName, commHandleEvent);//移除通用处理
            }
        } else {
            element.removeEventListener(eventName, commHandleEvent);//移除通用处理
        }
        return this;
    },
    /***
     * 触发事件
     * ****/
    trigger: function (eventName, args) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.trigger.call(element[i], eventName, args);
            }
            return this;
        }
        if (element.events) {
            var namespace = "";
            if (eventName.indexOf(".") > 0) {
                let arr = eventName.split(".");
                namespace = arr[0];
                eventName = arr[1];
            }
            let handlers = element.events[eventName];
            if(!handlers){
                return;
            }
            let keys = Object.keys(handlers);
            let pr = { target: element, isTrigger: true, params: {} };
            if (args) {
                Object.assign(pr, args);
            }
            for (let i = 0; i < keys.length; i++) {
                let evObj = handlers[keys[i]];
                if (namespace === "" || namespace === evObj.namespace) {
                    pr.params = evObj.params;
                    evObj.fn.call(element, pr);
                }
            }
        }
        return this;
    },
    /***
     * 解除element元素的某一类事件
     * eventName=click、mousedown、mouseup 事件名称或者 namespace.eventName 或者 namespace.*
     * ***/
    offEvents: function (eventName) {        
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.offEvents.call(element[i], eventName);
            }
            return this;
        }
        if (element.events) {
            if (eventName) {
                DomApiObj.removeListener.call(element, eventName);
            } else {
                var eventNames = Object.keys(element.events);
                for (var i = 0; i < eventNames.length; ++i) {
                    DomApiObj.removeListener.call(element, eventNames[i]);
                }
            }
        }
        return this;
    },
    /***
     * 批量绑定事件
     * events = {
     *      click:fn,
     *      dblclick:fn
     * }
     * ***/
    bind: function (events) {
        if (!_isLiteralObject(events)) {
            throw new Error("events is not a  object {}");
        }
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.bind.call(element[i], events);
            }
            return this;
        }
        let keys = Object.keys(events);
        for (let i = 0; i < keys.length; i++) {
            let eventName = keys[i];
            if (DomApiObj[eventName]) {
                DomApiObj[eventName].call(element, events[eventName]);
            }
        }
        return this;
    },
    click: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.click.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "click", listener);
        return this;
    },
    paste:function(listener){
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.paste.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "paste", listener);
        return this;
    },
    contextmenu: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.contextmenu.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "contextmenu", listener);
        return this;
    },
    dblclick: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.dblclick.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "dblclick", listener);
        return this;
    },
    mouseover: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseover.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseover", listener);
        return this;
    },
    mouseout: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseout.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseout", listener);
        return this;
    },
    mousedown: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mousedown.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mousedown", listener);
        return this;
    },
    mouseup: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseup.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseup", listener);
        return this;
    },
    mouseenter: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseenter.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseenter", listener);
        return this;
    },
    mouseleave: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mouseleave.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mouseleave", listener);
        return this;
    },
    mousemove: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.mousemove.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "mousemove", listener);
        return this;
    },
    touchstart: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.touchstart.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "touchstart", listener);
        return this;
    },
    touchend: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.touchend.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "touchend", listener);
        return this;
    },
    touchmove: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.touchmove.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "touchmove", listener);
        return this;
    },
    touchcancel: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.touchcancel.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "touchcancel", listener);
        return this;
    },
    focus: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.focus.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "focus", listener);
        return this;
    },
    blur: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.blur.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "blur", listener);
        return this;
    },
    select: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.select.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "select", listener);
        return this;
    },
    change: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.change.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "change", listener);
        return this;
    },
    submit: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.submit.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "submit", listener);
        return this;
    },
    reset: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.reset.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "reset", listener);
        return this;
    },
    onload: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.onload.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "load", listener);
        return this;
    },
    scroll: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.scroll.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "scroll", listener);
        return this;
    },
    unload: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.unload.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "unload", listener);
        return this;
    },
    resize: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.resize.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "resize", listener);
        return this;
    },
    keydown: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.keydown.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "keydown", listener);
        return this;
    },
    keyup: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.keyup.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "keyup", listener);
        return this;
    },
    keypress: function (listener) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.keypress.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "keypress", listener);
        return this;
    },
    input:function(listener){
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            for (let i = 0; i < element.length; i++) {
                DomApiObj.input.call(element[i], listener);
            }
            return this;
        }
        DomApiObj.addListener.call(element, "input", listener);
        return this;
    },
    /**
     * 是否是dom元素
     * @param {object} element
     * @returns {boolean}
     */
    isElement: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (typeof HTMLElement === 'object') {
            return element instanceof HTMLElement;
        }
        return element && typeof element === 'object' && element.nodeType === 1 && typeof element.nodeName === 'string';
    },
    /**
     * 是否是 DOMNode
     * @param node
     * @returns {*}
     */
    isNode: function () {
        var node = this;
        if (this._el) {
            node = this._el;
        }
        if (_isArray(node)) {
            node = node[0];
        }
        if (typeof Node === 'object') {
            return node instanceof Node;
        }
        return node && typeof node === 'object' && typeof node.nodeType === 'number' && typeof node.nodeName === 'string';
    },
    /***
     * 获取元素element，位置、高宽信息
     * ***/
    domInfo: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isElement.call(element)) {
            return false;
        }
        var rect = element.getBoundingClientRect();
        var info = {
            top: parseFloat(rect.top.toFixed(2)), //Math.round(rect.top)
            right: parseFloat(rect.right.toFixed(2)),
            bottom: parseFloat(rect.bottom.toFixed(2)),
            left: parseFloat(rect.left.toFixed(2)),
            width: rect.width ? parseFloat(rect.width.toFixed(2)) : parseFloat(element.offsetWidth.toFixed(2)),
            height: rect.height ? parseFloat(rect.height.toFixed(2)) : parseFloat(element.offsetHeight.toFixed(2))
        };
        if (info.width <= 0) {
            info.width = parseFloat(_getComputedStyle(element, 'width'));
        }
        if (info.height <= 0) {
            info.height = parseFloat(_getComputedStyle(element, 'height'));
        }
        let docElem = document.documentElement;
        let scrollTop = docElem.scrollTop;
        let scrollLeft = docElem.scrollLeft;
        info.pageTop = info.top + scrollTop;
        info.pageLeft = info.left + scrollLeft;
        info.scrollHeight = element.scrollHeight;
        info.scrollWidth = element.scrollWidth;
        info.offsetWidth = element.offsetWidth;
        info.offsetHeight = element.offsetHeight;
        info.pageScrollTop = scrollTop;
        info.pageScrollLeft = scrollLeft;
        info.elScrollTop = element.scrollTop;
        info.elScrollLeft = element.scrollTop;
        return info;
    },
    /*****
     * selector api 返回数组
     * element：元素
     * selector：刷选条件
     * *****/
    findBySelector: function (selector) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        var result = [];
        if (DomApiObj.isNode.call(element)) {
            result = element.querySelectorAll(selector);
            result = Array.from(result);
        } else {
            result = document.querySelectorAll(selector);
            result = Array.from(result);
        }

        return result;
    },
    findById:function(args){
        return this.findbyId(args);
    },
    findByid:function(args){
        return this.findbyId(args);
    },
    /***
     * 根据id查找元素
     * arg1:id / dom元素
     * arg2:当arg1是dom时候，arg2为id
     * ***/
    findbyId: function (arg2) {
        var arg1 = this;
        if (this._el) {
            arg1 = this._el;
        }
        if (_isArray(arg1)) {
            arg1 = arg1[0];
        }
        if (typeof arg2 === "undefined") {
            if (arg1.substring(0, 1) === "#") {
                arg1 = arg2.substring(1);
            }
            return document.getElementById(arg1);
        } else {
            if (arg1.querySelector) {
                if (arg2.substring(0, 1) !== "#") {
                    arg2 = "#" + arg2;
                }
                return arg1.querySelector(arg2);
            } else {
                if (arg2.substring(0, 1) === "#") {
                    arg2 = arg2.substring(1);
                }
                return document.getElementById(arg1);
            }

        }
    },
    /***
     * 根据tag Name查询元素
     * arg1:name / dom元素
     * arg2:当arg1是dom时候，arg2为name
     * ***/
    findByTagName: function (arg2) {       
        var arg1 = this;
        if (this._el) {
            arg1 = this._el;
        }
        if (_isArray(arg1)) {
            arg1 = arg1[0];
        }
        let ret;
        let s;
        if (typeof arg2 === "undefined") {
            s = getNameAndAttr(arg1);
            ret = document.getElementsByTagName(s.name);           
        } else {
            s = getNameAndAttr(arg2);
            ret = arg1.querySelectorAll(s.name);
        }
        if(s.attr){
            let res = [];
            let arr = s.attr.split("=");
            let name = arr[0];
            let val = arr[1];
            for(let i =0 ; i < ret.length ;i++){
                let el = ret[i];
                if($B.DomUtils.attribute(el,name) === val){
                    res.push(el);
                }
            }
            ret = res;
        }else{
            ret = Array.from(ret);
        }
        return ret;
    },
    /***
     * 根据class查询元素
     * arg1：className / dom元素
     * arg2：当arg1是dom元素，arg2位className
     * ***/
    findByClass: function (arg2) {
        var arg1 = this;
        if (this._el) {
            arg1 = this._el;
        }
        if (_isArray(arg1)) {
            arg1 = arg1[0];
        }
        let ret;
        if (typeof arg2 === "undefined") {
            if (arg1.substring(0, 1) === ".") {
                arg1 = arg1.substring(1);
            }
            if (document.querySelectorAll) {
                ret = document.querySelectorAll("." + arg1);
            }
            if (document.getElementsByClassName) {
                ret = document.getElementsByClassName(arg1);
            }
        } else if (arg1.querySelectorAll) {
            if (arg2.substring(0, 1) !== ".") {
                arg2 = "." + arg2;
            }
            ret = arg1.querySelectorAll(arg2);
        }
        var arr = [];
        for (let i = 0; i < ret.length; i++) {
            arr.push(ret[i]);
        }
        return arr;
    },
    /***
     * 获取元素element的父元素
     * ***/
    parent: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        return element.parentNode;
    },
    /***
     * 获取element的子元素，arg:元素名称 / className / id / true获取包含文本元素的所有子元素
     * ****/
    children: function (arg) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        let _type = typeof arg;
        if (_type === 'boolean' && arg) {
            return element.childNodes;
        }
        var result = [], i, child;
        if (_isString(arg)) {
            let firstChar = arg.substring(0, 1);
            let tagName = arg.toLowerCase();
            if (firstChar === "#") {
                let r = DomApiObj.getChildrenById.call(element, arg);
                return r;
            }
            if (firstChar === ".") {
                return DomApiObj.getChildrenByClass.call(element, arg);
            }
            for (i = 0; i < element.childNodes.length; i++) {
                child = element.childNodes[i];
                if (child.nodeName.toLowerCase() === tagName) {
                    result.push(child);
                }
            }

            return result;
        }
        for (i = 0; i < element.childNodes.length; ++i) {
            child = element.childNodes[i];
            if (child.nodeType === 1) {
                result.push(child);
            }
        }
        return result;
    },
    /***
     * 根据className 获取element的子元素
     * ****/
    getChildrenByClass: function (clazz) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        var ret = [];
        var childs = element.children;
        for (var i = 0; i < childs.length; i++) {
            if (DomApiObj.hasClass.call(childs[i], clazz)) {
                ret.push(childs[i]);
            }
        }
        return ret;
    },
    /***
     * 根据id获取element元素的子元素
     * ***/
    getChildrenById: function (id) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        var childs = element.children;
        if (id.indexOf("#") === 0) {
            id = id.substring(1);
        }
        for (var i = 0; i < childs.length; i++) {
            if (id === DomApiObj.attribute.call(childs[i], "id")) {
                return childs[i];
            }
        }
        return undefined;
    },
    /**
     * 根据标签名称获取element的子元素
     * ****/
    getChildrenByName: function (name) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        var ret = [];
        var childs = element.children;
        var isArr = _isArray(name);
        for (var i = 0; i < childs.length; i++) {
            if (isArr) {
                if (_isInArray(childs[i].nodeName, name)) {
                    ret.push(childs[i]);
                }
            } else {
                if (childs[i].nodeName === name) {
                    ret.push(childs[i]);
                }
            }
        }
        return ret;
    },
    /***
     * 获取所有相邻节点
     * canTextNode是否包括文本节点,或者是class类名
     * *****/
    siblings: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }        
        var nextAll = DomApiObj.nextAll.call(element, canTextNode);
        var preAll = DomApiObj.previousAll.call(element, canTextNode);
        preAll.push.apply(preAll, nextAll);
        return preAll;
    },
    forSiblings:function(fn){
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }  
        let prev = element.previousSibling;  
        while(prev ){
            if(prev.nodeType === 1){
               let r = fn(prev);
               if(r !== undefined && !r){
                    break;
               }
            }
            prev = prev.previousSibling;
        }   
        let next = element.nextSibling;  
        while(next ){
            if(next.nodeType === 1){               
                let r = fn(next);
               if(r !== undefined && !r){
                    break;
               }
            }
            next = next.nextSibling;
        }  
    },
    /**
     * 获取元素的下一个同级元素，
     * canTextNode：是否包括文本节点
     * ****/
    next: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        var result = element.nextSibling;
        if (!result) {
            return;
        }
        if (canTextNode) {
            return result;
        }
        if (result.nodeType !== 1) {
            return DomApiObj.next.call(result);
        }
        return result;
    },
    /***
     * 获取element元素后面的所有同级元素
     * canTextNode：是否包括文本节点,或者是class类名
     * ***/
    nextAll: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        let clz = (typeof canTextNode === "string" && canTextNode.indexOf(".")) === 0 ? canTextNode : undefined;
        if(clz){
            canTextNode = false;
        }
        var ret = [];
        var nextEle = DomApiObj.next.call(element, canTextNode);
        while (nextEle) {
            if(clz){
                if(DomApiObj.hasClass.call(nextEle,clz)){
                    ret.push(nextEle);
                }              
            }else{
                ret.push(nextEle);
            }            
            nextEle = DomApiObj.next.call(nextEle, canTextNode);
        }
        return ret;
    },
    /***
     * 获取element元素的前一个同级元素
     * canTextNode：是否包括文本节点
     * ***/
    previous: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        var result = element.previousSibling;
        if (!result) {
            return;
        }
        if (canTextNode) {
            return result;
        }
        if (result.nodeType !== 1) {
            return DomApiObj.previous.call(result);
        }
        return result;
    },
    /***
     * 获取element元素的前所有的同级元素
     * canTextNode：是否包括文本节点,或者是class类名
     * ***/
    previousAll: function (canTextNode) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        let clz = (typeof canTextNode === "string" && canTextNode.indexOf(".")) === 0 ? canTextNode : undefined;
        if(clz){
            canTextNode = false;
        }
        var ret = [];
        var preEle = DomApiObj.previous.call(element, canTextNode);
        while (preEle) {
            if(clz){
                if(DomApiObj.hasClass.call(preEle,clz)){
                    ret.unshift(preEle);
                }                
            }else{
                ret.unshift(preEle);
            } 
            preEle = DomApiObj.previous.call(preEle, canTextNode);
        }
        return ret;
    },
    /****
     * 设置/获取element的属性,获取属性:attribute=string/[s1,s2]
     * 设置属性attribute={}
     * ****/
    attribute: function (attribute) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr && _isLiteralObject(attribute)) { //多个元素同时设置属性
            _each(element, function (e) {
                DomApiObj.attribute.call(e, attribute);
            });
            return this;
        }
        if (isArr) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        var result, i, keys;
        //获取一个属性
        if (typeof attribute === "string") {
            if (attribute === 'class' && element['className'] !== undefined) {//class
                result = element.className;
            } else if (attribute === 'for' && element['htmlFor'] !== undefined) {//for
                result = element.htmlFor;
            } else if (attribute === 'value' && element['value'] !== undefined) {//value?               
                return element.value;
            } else {
                if(attribute === "checked"){
                    result =   element.checked;
                }else{
                    result = element.getAttribute(attribute);
                }
            }            
            if (result === null) {
                result = undefined;
            }
            return result;
        }
        //获取多个
        if (_isArray(attribute)) {
            keys = Object.keys(attribute);
            for (i = 0; i < keys.length; ++i) {
                result[attribute[keys[i]]] = DomApiObj.attribute.call(element, attribute[keys[i]]);
            }
            return result;
        }
        //设置属性
        if (_isLiteralObject(attribute)) {
            keys = Object.keys(attribute);
            for (i = 0; i < keys.length; ++i) {
                if (attribute[keys[i]] === null || attribute[keys[i]] === undefined) {
                    element.removeAttribute(keys[i]);
                    if(keys[i] === "checked"){
                        element.checked = false;
                    }
                    if(keys[i] === "selected"){
                        element.selected = false;
                    }
                } else {                   
                    if(keys[i] === "checked"){
                        element.checked = attribute[keys[i]];
                    }else if(keys[i] === "selected"){
                        element.selected = attribute[keys[i]];
                    }else{
                        element.setAttribute(keys[i], attribute[keys[i]]);
                    }
                }
            }
            return this;
        }
    },
    /***
     * 获取或者设置元素element的宽度
     * ***/
    width: function (width) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "width", width);
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /***
     * 获取或者设置元素element的高度
     * ***/
    height: function (height) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "height", height);
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /**
     * 获取或者设置元素element的内宽度
     * ***/
    innerWidth: function (width) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "width", width, "inner");
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /**
     * 获取或者设置元素element的内高度
     * ***/
    innerHeight: function (height) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "height", height, "inner");
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /**
     * 获取或者设置元素element的外宽度
     * ***/
    outerWidth: function (width) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "width", width, "outer");
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /**
     * 获取或者设置元素element的外高度
     * ***/
    outerHeight: function (height) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = getSetWH(element, "height", height, "outer");
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /****
     * 设置/获取element元素的scrollLeft
     * *****/
    scrollLeft: function (left) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = _getSetScroll(element, "scrollLeft", left);
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /****
     * 设置/获取element元素的scrollTop
     * *****/
    scrollTop: function (top) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var ret = _getSetScroll(element, "scrollTop", top);
        if (typeof ret === "undefined") {
            return this;
        }
        return ret;
    },
    /***
     * 设置/获取element元素的position
     * *****/
    position: function (pos) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (pos) {//设置位置
            DomApiObj.css.call(element, pos);
            return this;
        } else {//获取位置属性
            if (Array.isArray(element)) {
                element = element[0];
            }
            var offsetParent, offset,
                parentOffset = { top: 0, left: 0 };
            if (!DomApiObj.inDom.call(element)) {
                return parentOffset;
            }
            if (DomApiObj.css.call(element, "position") === "fixed") {
                offset = element.getBoundingClientRect();
            } else {
                offsetParent = DomApiObj.getOffsetParent.call(element);
                offset = DomApiObj.offset.call(element);
                if (offsetParent.nodeName.toLowerCase() !== "html") {
                    parentOffset = DomApiObj.offset.call(offsetParent);
                }
                parentOffset.top += DomApiObj.css.call(offsetParent, "borderTopWidth");
                parentOffset.left += DomApiObj.css.call(offsetParent, "borderLeftWidth");
            }
            return {
                top: offset.top - parentOffset.top - DomApiObj.css.call(element, "marginTop"),
                left: offset.left - parentOffset.left - DomApiObj.css.call(element, "marginLeft")
            };
        }
    },
    /***
     * 元素是否脱离了文档
     * ***/
    inDom() {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isArray(element)) {
            element = element[0];
        }
        let r = window.document.contains(element);
        if(!r){
            let prt = element.parentNode;
            while(prt){
                if(prt.nodeName === "BODY"){                  
                    r = true;
                    break;
                }
                prt = prt.parentNode;
            }
        }
        return r;
    },
    /***
     * 获取element元素相对位置的参考父元素
     * ****/
    getOffsetParent() {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        var offsetParent = element.offsetParent;
        while (offsetParent && offsetParent.nodeName.toLowerCase() !== "html" && DomApiObj.css.call(offsetParent, "position") === "static") {
            offsetParent = offsetParent.offsetParent;
        }
        return offsetParent || document.documentElement;
    },
    /***
     * 获取element的相对视窗的偏移量数据
     * ****/
    offset: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        var ofs = {
            top: 0,
            left: 0
        };
        if (!DomApiObj.inDom.call(element)) {
            return ofs;
        }
        if (element.getBoundingClientRect) {
            let box = element.getBoundingClientRect();
            ofs.top = box.top;
            ofs.left = box.left;
        }
        let docElem = element.ownerDocument.documentElement;
        let ret = {
            top: ofs.top + (window.pageYOffset || docElem.scrollTop) - (docElem.clientTop || 0),
            left: ofs.left + (window.pageXOffset || docElem.scrollLeft) - (docElem.clientLeft || 0)
        };
        return ret;
    },
    /****
     * 设置/获取元素的css样式，获取时候style参数必须是字符串的css名称
     * ****/
    css: function (style) {       
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr && _isLiteralObject(style)) { //多个元素一起设置样式
            _each(element, function (e) {
                DomApiObj.css.call(e, style);
            });
            return this;
        }
        if (isArr) { //是数组
            if(element.length === 0){
                return;
            }
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        if (typeof style === "string") {
            return _getComputedStyle(element, cssNameProperty(style));
        }
        var keys, i;
        if (_isArray(style)) {
            var css = {};
            keys = Object.keys(style);
            for (i = 0; i < keys.length; ++i) {
                css[style[keys[i]]] = _getComputedStyle(element, cssNameProperty(style[keys[i]]));
            }
            return css;
        }
        if (_isLiteralObject(style)) {
            keys = Object.keys(style);
            for (i = 0; i < keys.length; ++i) {
                let cName = cssNameProperty(keys[i]);
                let value = style[keys[i]] + "";                              
                if (value.indexOf("#") < 0 && value.indexOf("%") < 0 && /^-?\d+\.?\d*$/.test(value) && !CSSNumber[cName]) {
                    value = value + "px";
                }
                if(cName === "backgroundColor" && value === "none"){
                    value = "transparent";
                }
                element.style[cName] = value;
            }
            return this;
        }
    },
    /***
     * 获取元素element的class
     * ***/
    getClass: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        var attribute = DomApiObj.attribute.call(element, 'class');
        if (!attribute) {
            return [];
        }
        attribute = attribute.split(' ');
        var classNames = [], keys, i;
        keys = Object.keys(attribute);
        for (i = 0; i < keys.length; ++i) {
            if (attribute[keys[i]] === '') {
                continue;
            }
            classNames.push(attribute[keys[i]]);
        }
        return classNames;
    },
    /***
     * element元素是否存在className，className可以是数组
     * ****/
    hasClass: function (className) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        if (_isString(className)) {
            if (className.indexOf(".") === 0) {
                className = className.substring(1);
            }
            return _indexOf(DomApiObj.getClass.call(element), className) > -1 ? true : false;
        } else if (_isArray(className)) {
            var elementClasses = DomApiObj.getClass.call(element);
            for (var i = 0; i < className.length; i++) {
                if (_indexOf(className[i], elementClasses) === -1) {
                    return false;
                }
            }
            return true;
        } else {
            return false;
        }
    },
    /****
     * element元素添加class
     * ****/
    addClass: function (className) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isIterable(element)) {
            _each(element, function (e) {
                DomApiObj.addClass.call(e, className);
            });
            return this;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error(element + " is not a DOMNode object");
        }
        if (_isArray(className)) {
            var i, keys = Object.keys(className);
            for (i = 0; i < keys.length; i++) {
                DomApiObj.addClass.call(element, className[keys[i]]);
            }
            return DomUtils;
        }
        var classes = DomApiObj.getClass.call(element);
        if (_indexOf(classes, className) === -1) {
            classes.push(className);
        }
        classes = classes.join(' ');
        DomApiObj.attribute.call(element, { class: classes });
        return this;
    },
    /*****
     * 移除元素的class
     * ******/
    removeClass: function (className) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (_isIterable(element)) {
            _each(element, function (e) {
                DomApiObj.removeClass.call(e, className);
            });
            return this;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.removeClass" + element + " is not a DOMNode object");
        }
        if (!className) {
            return DomApiObj.attribute.call(element, { class: "" });
        }     
        var classes = DomApiObj.getClass.call(element);
        var arr = className.split(/\s+/);
        for (let i = 0; i < arr.length; i++) {
            let j = _indexOf(classes, arr[i]);
            if (j !== -1) {
                classes.splice(j, 1);
            }
        }
        DomApiObj.attribute.call(element, { class: classes.join(' ') });
        return this;
    },
    /***
     * 复制元素
     * isDeep是否深复制，复制数据及事件
     * ****/
    copy: function (isDeep) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.copy" + element + " is not a DOMNode object");
        }
        var newEl = element.cloneNode(true);
        if (isDeep) {
            var events = element.events;
            if (events) {
                newEl.events = events;//复用复制的事件
                let namekeys = Object.keys[events];
                for (let i = 0; i < namekeys.length; i++) {
                    let eventName = namekeys[i];
                    if (newEl.addEventListener) {
                        newEl.addEventListener(eventName, commHandleEvent, false);
                    } else {
                        newEl["on" + eventName] = commHandleEvent;
                    }
                }
            }
            var _eldata = element._eldata;
            if (_eldata) {
                newEl._eldata = _eldata;
            }
        }
        return newEl;
    },
    /**
     * 往元素设置/读取html内容
     * ***/
    html: function (string) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr && _isString(string)) {
            _each(element, function (e) {
                DomApiObj.html.call(e, string);
            });
            return this;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.html" + element + " is not a DOMNode object");
        }
        if (_isString(string)) {
            element.innerHTML = string;
            return this;
        }
        element = _getArrayFirstEl(element);
        return element.innerHTML;
    },
    /**
     * 往元素设置/读取innertText
     * ***/
    text: function (string) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr && _isString(string)) {
            _each(element, function (e) {
                DomApiObj.text.call(e, string);
            });
            return this;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.text " + element + " is not a DOMNode object");
        }
        if (_isString(string)) {
            if (element.innerText) {
                element.innerText = string;
            } else {
                element.textContent = string;
            }
            return this;
        }
        element = _getArrayFirstEl(element);
        if (element.innerText) {
            return element.innerText;
        }
        return element.textContent;
    },
    /***
     * 设置或者获取元素的value值
     * ***/
    value: function (value) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        var hooks, ret;
        if (typeof value === "undefined") {//获取值
            hooks = valHooks[element.nodeName.toLowerCase()];
            if (hooks && hooks.get) {
                return hooks.get(element);
            }
            ret = element.value;
            return typeof ret === "string" ? _trim(ret) : ret == null ? "" : ret;
        } else {//设置值
            hooks = valHooks[element.nodeName.toLowerCase()];
            if (hooks && hooks.set) {
                return hooks.set(element);
            }
            element.value = value;
        }
        return this;
    },
    /**
     * 判定元素是否处于隐藏状态
     * ***/
    isHide: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        return DomApiObj.css.call(element, "display") === "none";
    },
    /***
     * 显示元素
     * ***/
    show: function (animate) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.show.call(e);
            });
            return this;
        }
        if (animate && animate.length > 1) {
            let args = [];
            for (let i = 0; i < animate.length; i++) {
                args.push(animate[i]);
            }
            $B.show.apply(this, args);
        } else {
            element.style.display = "";
            if(  element.style.opacity === '0' || element.style.opacity === 0){
                element.style.opacity = 1;
            }
        }
        return this;
    },
    /**
     * 隐藏元素
     * ***/
    hide: function (animate) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.hide.call(e);
            });
            return this;
        }
        if (animate && animate.length > 1) {
            let args = [];
            for (let i = 0; i < animate.length; i++) {
                args.push(animate[i]);
            }
            $B.hide.apply(this, args);
        } else {
            //element.style.display = "";
            element.style.display = "none";
        }
        return this;
    },
    /**
     * 将html/元素添加到element元素内部的后面
     * ***/
    append: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'append', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.append " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.append.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }     
        if(Array.isArray(html)){
            for(let i =0 ; i < html.length ;i++){
                element.appendChild(html[i]);
            }
        }else{
            element.appendChild(html);
        }
        clearTimeout(_onNodeRemoveEventTimer);
        return html;
    },
    /**
     * 将html/元素添加到element元素内部的前面
     * ***/
    prepend: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'prepend', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.prepend " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.prepend.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }
        if(Array.isArray(html)){
            for(let i =0 ; i < html.length ;i++){
                element.insertBefore(html[i], element.firstChild);
            }
        }else{
            element.insertBefore(html, element.firstChild);
        }        
        clearTimeout(_onNodeRemoveEventTimer);
        return html;
    },
    /***
     * 将html/元素插入到element后面
     * ***/
    after: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'after', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.after " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.after.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }
        if(Array.isArray(html)){
            for(let i =0 ; i < html.length ;i++){
                element.parentNode.insertBefore(html[i], element.nextSibling);
            }
        }else{
            element.parentNode.insertBefore(html, element.nextSibling);
        }        
        clearTimeout(_onNodeRemoveEventTimer);
        return html;
    },
    /***
     * 将html/元素插入到element前面
     * ***/
    before: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'before', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.before " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.before.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }
        if(Array.isArray(html)){
            for(let i =0 ; i < html.length ;i++){
                element.parentNode.insertBefore(html[i], element);
            }
        }else{
            element.parentNode.insertBefore(html, element);
        }        
        clearTimeout(_onNodeRemoveEventTimer);
        return html;
    },
    /***
     * 将html/元素替换element前面
     * ***/
    replace: function (html) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var res = _elementInsert(element, 'replace', html);
        if (res) {
            return res;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.replace " + element + " is not a DOMNode object");
        }
        if (Array.isArray(html)) {
            var ret = [];
            for (let i = 0; i < html.length; i++) {
                ret.push(DomApiObj.replace.call(element, html[i]));
            }
            return ret;
        }
        if (_isString(html)) {
            html = DomUtils.createEl(html);
        }
        DomApiObj.clearElement.call(element);
        element.parentNode.replaceChild(html, element);
        return html;
    },
    /**
     * 清理element的数据和事件
     * **/
    clearElement: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (forachExecute(element, "clearElement")) {
            return this;
        }
        element._eldata = undefined;
        var events = element.events;
        if (events) {
            element.events = undefined;
            var eventKeys = Object.keys(events);
            for (let i = 0; i < eventKeys.length; i++) {
                let eventName = eventKeys[i];
                element.removeEventListener(eventName, commHandleEvent);//移除通用处理
                events[eventName] = undefined;
            }
        }
        return this;
    },
    /**
     * 移除element下所有子元素
     * 或者是某个class的子元素
     * **/
    removeChilds: function (args) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (forachExecute(element, "removeChilds")) {
            return this;
        }
        var ret = [];
        for (let i = 0; i < element.childNodes.length; i++) {
            let child = element.childNodes[i];
            if (args ) {
                if ( child.nodeType === 1  && args.indexOf(".") === 0) { //按class
                    if (DomApiObj.hasClass.call(child, args.substring(1))) {
                        ret.push(child);
                    }
                }
            } else {
                ret.push(child);
            }
        }
        for (let i = 0; i < ret.length; i++) {
            let child = ret[i];
            DomApiObj.clearElement.call(child);
            element.removeChild(child);
        }
        return ret;
    },
    /**
     * 移除element元素,会将相关数据和事件移除
     * ***/
    remove: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (forachExecute(element, "remove")) {
            return;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.remove " + element + " is not a DOMNode object");
        }
        var parent = element.parentNode;
        DomApiObj.clearElement.call(element);
        if (parent) {
            return parent.removeChild(element);
        }
        return element;
    },
    /**
     * 移除element元素,并且还保留数据和事件移除
     * ***/
    detach: function () {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        let exeRet = forachExecute(element, "detach");
        if (exeRet) {
            return exeRet;
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.remove " + element + " is not a DOMNode object");
        }
        var parent = element.parentNode;
        if(parent){
            element._isRetainEvent = true; //跳过domRemove监听，不需要清除元素上的数据和事件   
            parent.removeChild(element);
            setTimeout(function () {
                element._isRetainEvent = undefined;
            }, 10);
        }       
        return element;
    },
    /***
     * 移除element下的所有元素（保留事件-数据），并将这些元素数组形式返回
     * ***/
    detachChilds: function (args) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        if (Array.isArray(element)) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.remove " + element + " is not a DOMNode object");
        }
        var ret = [];
        while (element.childNodes.length > 0) {
            let child = element.childNodes[0];
            if (args) {
                if (args.indexOf(".") === 0) { //按class
                    if (!DomApiObj.hasClass.call(child, args.substring(1))) {
                        continue;
                    }
                }
            }
            DomApiObj.detach.call(child);
            if (!(child.nodeType === 3 && $B.replaceSpaceChar(child.nodeValue) === "")) {
                ret.push(child);
            }
        }
        return ret;
    },
    /***
     * 设置，读取简单类型的属性，属性数据会在标签上形成data-xxx属性
     * args:属性名称，或者{prop:value},移除数据用{name:undefined/null}
     * ***/
    propData: function (args) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        var isSet = _isLiteralObject(args);
        if (isArr && isSet) {
            _each(element, function (e) {
                DomApiObj.propData.call(e, args);
            });
            return true;
        }
        if (isArr) {
            element = element[0];
        }
        if (!DomApiObj.isNode.call(element)) {
            throw new Error("DomUtils.data " + element + " is not a DOMNode object");
        }
        var i, dataset, attrs, keys, attr, l;
        //获取元素上的所有数据
        if (args === undefined) {
            if (element.hasOwnProperty('dataset')) {
                return element.dataset;
            } else {//通过属性获取
                dataset = {};
                for (i = 0, l = element.attributes.length; i < l; i++) {
                    attr = element.attributes.item(i);
                    if (attr.nodeName.substr(0, 5) !== 'data-') {
                        continue;
                    }
                    dataset[attr.nodeName.substr(5)] = attr.nodeValue;
                }
                return dataset;
            }
        }
        //获取一个属性
        if (_isString(args)) {
            return DomApiObj.attribute.call(element, 'data-' + args);
        }
        //获取多个数据
        if (_isArray(args)) {
            dataset = {};
            for (i = 0, l = args.length; i < l; i++) {
                dataset[args[i]] = DomApiObj.attribute.call(element, 'data-' + args[i]);
            }
            return dataset;
        }
        //设置数据{}
        if (isSet) {
            attrs = {};
            keys = Object.keys(args);
            for (i = 0; i < keys.length; ++i) {
                attrs['data-' + keys[i]] = args[keys[i]];
            }
            DomApiObj.attribute.call(element, attrs);
        }
        return this;
    },
    /***
     * 移除简单类型属性
     * key=属性名称
     * ****/
    removePropData: function (key) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.removePropData.call(e, key);
            });
            return;
        }
        key = "data-" + key;
        element.removeAttribute(key);
        return this;
    },
    removeAttribute: function (key) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.removeAttribute.call(e, key);
            });
            return;
        }
        element.removeAttribute(key);
        return this;
    },
    /**
     * 设置元素数据，key：数据key，dataObject数据对象
     * 该api会在element._eldata上生成数据对象
     * ***/
    setData: function (key, dataObject) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        var isArr = _isIterable(element);
        if (isArr) {
            _each(element, function (e) {
                DomApiObj.setData.call(e, key, dataObject);
            });
            return true;
        }
        var cached = element._eldata;
        if (!cached) {
            cached = {};
            element._eldata = cached;
        }
        if (dataObject === undefined || dataObject === null) {
            delete cached[key];
        } else {
            cached[key] = dataObject;
        }
        return this;
    },
    /***
     * 根据key获取element元素的数据
     * ***/
    getData: function (key) {
        var element = this;
        if (this._el) {
            element = this._el;
        }
        element = _getArrayFirstEl(element);
        var cached = element._eldata;
        if (!cached) {
            return undefined;
        }
        return cached[key];
    }
};
DomUtils = {
    $: function (arg1, arg2) {
        let el = arg1;
        var obj = {
            _el: el
        };
        obj["__proto__"] = DomApiObj;
        return obj;
    },
    /***
     * 对元素添加一个事件监听
     * element：元素
     * eventName ：事件名称,支持命名空间 namespac.click
     * listener:事件处理函数
     * params:额外的参数
     * **/
    addListener: function (element, eventName, listener, params) {
        return DomApiObj.addListener.call(element, eventName, listener, params);
    },
    /***
     * 对元素移除事件
     * element：元素
     * eventName ：事件名称,支持命名空间 namespac.click
     * listener:事件处理函数
     * **/
    removeListener: function (element, eventName, listener) {
        return DomApiObj.removeListener.call(element, eventName, listener);
    },
    /***
     * 触发事件
     * ****/
    trigger: function (element, eventName, args) {
        return DomApiObj.trigger.call(element, eventName, args);
    },
    /***
     * 接触element元素的某一类事件
     * eventName=click、mousedown、mouseup 事件名称或者 namespace.eventName 或者 namespace.*
     * ***/
    offEvents: function (element, eventName) {
        return DomApiObj.offEvents.call(element, eventName);
    },
    /***
     * 绑定事件
     * ***/
    bind: function (element, arg1, arg2) {
        if (_isLiteralObject(arg1)) {
            return DomApiObj.bind.call(element, arg1);
        } else if (_isFunction(arg2)) {
            if (DomApiObj[arg1]) {
                return DomApiObj[arg1].call(element, arg2);
            }
        }
    },
    click: function (element, listener) {
        return DomApiObj.click.call(element, listener);
    },
    contextmenu: function (element, listener) {
        return DomApiObj.contextmenu.call(element, listener);
    },
    paste:function(element, listener){
        return DomApiObj.paste.call(element, listener);
    },
    dblclick: function (element, listener) {
        return DomApiObj.dblclick.call(element, listener);
    },
    mouseover: function (element, listener) {
        return DomApiObj.mouseover.call(element, listener);
    },
    mouseout: function (element, listener) {
        return DomApiObj.mouseout.call(element, listener);
    },
    mousedown: function (element, listener) {
        return DomApiObj.mousedown.call(element, listener);
    },
    mouseup: function (element, listener) {
        return DomApiObj.mouseup.call(element, listener);
    },
    mouseenter: function (element, listener) {
        return DomApiObj.mouseenter.call(element, listener);
    },
    mouseleave: function (element, listener) {
        return DomApiObj.mouseleave.call(element, listener);
    },
    mousemove: function (element, listener) {
        return DomApiObj.mousemove.call(element, listener);
    },
    touchstart: function (element, listener) {
        return DomApiObj.touchstart.call(element, listener);
    },
    touchend: function (element, listener) {
        return DomApiObj.touchend.call(element, listener);
    },
    touchmove: function (element, listener) {
        return DomApiObj.touchmove.call(element, listener);
    },
    touchcancel: function (element, listener) {
        return DomApiObj.touchcancel.call(element, listener);
    },
    focus: function (element, listener) {
        return DomApiObj.focus.call(element, listener);
    },
    blur: function (element, listener) {
        return DomApiObj.blur.call(element, listener);
    },
    select: function (element, listener) {
        return DomApiObj.select.call(element, listener);
    },
    change: function (element, listener) {
        return DomApiObj.change.call(element, listener);
    },
    submit: function (element, listener) {
        return DomApiObj.submit.call(element, listener);
    },
    reset: function (element, listener) {
        return DomApiObj.reset.call(element, listener);
    },
    onload: function (element, listener) {
        return DomApiObj.onload.call(element, listener);
    },
    scroll: function (element, listener) {
        return DomApiObj.scroll.call(element, listener);
    },
    unload: function (element, listener) {
        return DomApiObj.unload.call(element, listener);
    },
    resize: function (element, listener) {
        return DomApiObj.resize.call(element, listener);
    },
    keydown: function (element, listener) {
        return DomApiObj.keydown.call(element, listener);
    },
    keyup: function (element, listener) {
        return DomApiObj.keyup.call(element, listener);
    },
    keypress: function (element, listener) {
        return DomApiObj.keypress.call(element, listener);
    },
    input:function(element, listener){
        return DomApiObj.input.call(element, listener);
    },
    /**
     * 是否是dom元素
     * @param {object} element
     * @returns {boolean}
     */
    isElement: function (element) {
        return DomApiObj.isElement.call(element);
    },
    /**
     * 是否是 DOMNode
     * @param node
     * @returns {*}
     */
    isNode: function (node) {
        return DomApiObj.isNode.call(node);
    },
    /***
     * 获取元素element，位置、高宽信息
     * ***/
    domInfo: function (element) {
        return DomApiObj.domInfo.call(element);
    },
    /*****
     * selector api 返回数组
     * element：元素
     * selector：刷选条件
     * *****/
    findBySelector: function (element, selector) {
        return DomApiObj.findBySelector.call(element, selector);
    },
    /***
     * 根据id查找元素
     * arg1:id / dom元素
     * arg2:当arg1是dom时候，arg2为id
     * ***/
    findbyId: function (arg1, arg2) {
        if(!arg2){
            arg2 = arg1;
            arg1 = document;
        }
        return DomApiObj.findbyId.call(arg1, arg2);
    },
    /***
     * 根据tag Name查询元素
     * arg1:name / dom元素
     * arg2:当arg1是dom时候，arg2为name
     * ***/
    findByTagName: function (arg1, arg2) {
        return DomApiObj.findByTagName.call(arg1, arg2);
    },
    /***
     * 根据class查询元素
     * arg1：className / dom元素
     * arg2：当arg1是dom元素，arg2位className
     * ***/
    findByClass: function (arg1, arg2) {
        return DomApiObj.findByClass.call(arg1, arg2);
    },
    /***
     * 获取元素element的父元素
     * ***/
    parent: function (element) {
        return DomApiObj.parent.call(element);
    },
    /***
     * 获取element的子元素，arg:元素名称 / className / id / true获取包含文本元素的所有子元素
     * ****/
    children: function (element, arg) {
        return DomApiObj.children.call(element, arg);
    },
    /***
     * 根据className 获取element的子元素
     * ****/
    getChildrenByClass: function (element, clazz) {
        return DomApiObj.getChildrenByClass.call(element, clazz);
    },
    /***
     * 根据id获取element元素的子元素
     * ***/
    getChildrenById: function (element, id) {
        return DomApiObj.getChildrenById.call(element, id);
    },
    /**
     * 根据标签名称获取element的子元素
     * ****/
    getChildrenByName: function (element, name) {
        return DomApiObj.getChildrenByName.call(element, name);
    },
    siblings: function (element, canTextNode) {
        return DomApiObj.siblings.call(element, canTextNode);
    },
    forSiblings:function (element, fn) {
        return DomApiObj.forSiblings.call(element, fn);
    },
    /**
     * 获取元素的下一个同级元素，
     * canTextNode：是否包括文本节点
     * ****/
    next: function (element, canTextNode) {
        return DomApiObj.next.call(element, canTextNode);
    },
    /***
     * 获取element元素后面的所有同级元素
     * canTextNode：是否包括文本节点
     * ***/
    nextAll: function (element, canTextNode) {
        return DomApiObj.nextAll.call(element, canTextNode);
    },
    /***
     * 获取element元素的前一个同级元素
     * canTextNode：是否包括文本节点
     * ***/
    previous: function (element, canTextNode) {
        return DomApiObj.previous.call(element, canTextNode);
    },
    /***
     * 获取element元素的前所有的同级元素
     * canTextNode：是否包括文本节点
     * ***/
    previousAll: function (element, canTextNode) {
        return DomApiObj.previousAll.call(element, canTextNode);
    },
    /***
     * 获取或者设置元素element的宽度
     * ***/
    width: function (element, width) {
        return DomApiObj.width.call(element, width);
    },
    /***
     * 获取或者设置元素element的高度
     * ***/
    height: function (element, height) {
        return DomApiObj.height.call(element, height);
    },
    /**
     * 获取或者设置元素element的内宽度
     * ***/
    innerWidth: function (element, width) {
        return DomApiObj.innerWidth.call(element, width);
    },
    /**
     * 获取或者设置元素element的内高度
     * ***/
    innerHeight: function (element, height) {
        return DomApiObj.innerHeight.call(element, height);
    },
    /**
     * 获取外部width/height
     * **/
    outerSize: function (element) {
        var w = DomApiObj.outerWidth.call(element);
        var h = DomApiObj.outerHeight.call(element);
        return {
            width: w,
            height: h
        };
    },
    /**
     * 获取或者设置元素element的外宽度
     * ***/
    outerWidth: function (element, width) {
        return DomApiObj.outerWidth.call(element, width);
    },
    /**
     * 获取或者设置元素element的外高度
     * ***/
    outerHeight: function (element, height) {
        return DomApiObj.outerHeight.call(element, height);
    },
    /****
     * 设置/获取element元素的scrollLeft
     * *****/
    scrollLeft: function (element, left) {
        return DomApiObj.scrollLeft.call(element, left);
    },
    /****
     * 设置/获取element元素的scrollTop
     * *****/
    scrollTop: function (element, top) {
        return DomApiObj.scrollTop.call(element, top);
    },
    /***
     * 设置/获取element元素的position
     * *****/
    position: function (element, pos) {
        return DomApiObj.position.call(element, pos);
    },
    /***
     * 元素是否脱离了文档
     * ***/
    inDom(element) {
        return DomApiObj.inDom.call(element);
    },
    /***
     * 获取element元素相对位置的参考父元素
     * ****/
    getOffsetParent(element) {
        return DomApiObj.getOffsetParent.call(element);
    },
    /***
     * 获取element的相对视窗的偏移量数据
     * ****/
    offset: function (element) {
        return DomApiObj.offset.call(element);
    },
    /****
     * 设置/获取元素的css样式，获取时候style参数必须是字符串的css名称
     * ****/
    css: function (element, style) {
        return DomApiObj.css.call(element, style);
    },
    /***
     * 获取元素element的class
     * ***/
    getClass: function (element) {
        return DomApiObj.getClass.call(element);
    },
    /***
     * element元素是否存在className，className可以是数组
     * ****/
    hasClass: function (element, className) {
        return DomApiObj.hasClass.call(element, className);
    },
    /****
     * element元素添加class
     * ****/
    addClass: function (element, className) {
        return DomApiObj.addClass.call(element, className);
    },
    /*****
     * 移除元素的class
     * ******/
    removeClass: function (element, className) {
        return DomApiObj.removeClass.call(element, className);
    },
    /***
     * 复制元素
     * isDeep是否深复制，复制数据及事件
     * ****/
    copy: function (element, isDeep) {
        return DomApiObj.copy.call(element, isDeep);
    },
    /**
     * 往元素设置/读取html内容
     * ***/
    html: function (element, string) {
        return DomApiObj.html.call(element, string);
    },
    /**
     * 往元素设置/读取innertText
     * ***/
    text: function (element, string) {
        return DomApiObj.text.call(element, string);
    },
    /***
     * 设置或者获取元素的value值
     * ***/
    value: function (element, value) {
        return DomApiObj.value.call(element, value);
    },
    /**
     * 判定元素是否处于隐藏状态
     * ***/
    isHide: function (element) {
        return DomApiObj.isHide.call(element);
    },
    /***
     * 显示元素
     * ***/
    show: function (element, args) {
        return DomApiObj.show.call(element, arguments);
    },
    /**
     * 隐藏元素
     * ***/
    hide: function (element, args) {
        return DomApiObj.hide.call(element, arguments);
    },
    /**
     * 将html/元素添加到element元素内部的后面
     * ***/
    append: function (element, html) {
        return DomApiObj.append.call(element, html);
    },
    /**
     * 将html/元素添加到element元素内部的前面
     * ***/
    prepend: function (element, html) {
        return DomApiObj.prepend.call(element, html);
    },
    /***
     * 将html/元素插入到element后面
     * ***/
    after: function (element, html) {
        return DomApiObj.after.call(element, html);
    },
    /***
     * 将html/元素插入到element前面
     * ***/
    before: function (element, html) {
        return DomApiObj.before.call(element, html);
    },
    /***
     * 将html/元素替换element
     * ***/
    replace: function (element, html) {
        return DomApiObj.replace.call(element, html);
    },
    /**
     * 清理element的数据和事件
     * **/
    clearElement: function (element) {
        if (!element || element.length === 0) {
            return;
        }
        return DomApiObj.clearElement.call(element);
    },
    /**
     * 移除element下所有子元素
     * **/
    removeChilds: function (element, clazz) {
        if (!element || element.length === 0) {
            return;
        }
        return DomApiObj.removeChilds.call(element, clazz);
    },
    /**
     * 移除element元素,会将相关数据和事件移除
     * ***/
    remove: function (element) {
        if (!element || element.length === 0) {
            return;
        }
        return DomApiObj.remove.call(element);
    },
    /**
     * 移除element元素,并且还保留数据和事件移除
     * ***/
    detach: function (element) {
        return DomApiObj.detach.call(element);
    },
    /***
     * 移除element下的所有元素（保留事件-数据），并将这些元素数组形式返回
     * ***/
    detachChilds: function (element, args) {
        return DomApiObj.detachChilds.call(element, args);
    },
    /***
     * 设置，读取简单类型的属性，属性数据会在标签上形成data-xxx属性
     * args:属性名称，或者{prop:value},移除数据用{name:undefined/null}
     * ***/
    propData: function (element, args) {
        return DomApiObj.propData.call(element, args);
    },
    /***
     * 移除简单类型属性
     * key=属性名称
     * ****/
    removePropData: function (element, key) {
        return DomApiObj.removePropData.call(element, key);
    },
    removeAttribute: function (element, key) {
        return DomApiObj.removeAttribute.call(element, key);
    },
    removeAttr:function(element, key){
        return DomApiObj.removeAttribute.call(element, key);
    },
    attribute: function (element, args) {
        return DomApiObj.attribute.call(element, args);
    },
    attr:function(element, args){
        return DomApiObj.attribute.call(element, args);
    },
    removeData: function (element, key) {
        return DomApiObj.setData.call(element, key);
    },
    /**
     * 设置元素数据，key：数据key，dataObject数据对象
     * 该api会在element._eldata上生成数据对象
     * ***/
    setData: function (element, key, dataObject) {
        return DomApiObj.setData.call(element, key, dataObject);
    },
    /***
     * 根据key获取element元素的数据
     * ***/
    getData: function (element, key) {
        return DomApiObj.getData.call(element, key);
    },
    /***
     * 根据html创建元素，这个api需要进一步验证
     * *****/
    createEl: function (html) {
        var parent;
        if (/^<td/.test(html) || /^<th/.test(html)) {
            parent = document.createElement("tr");
        } else if (/^<tr/.test(html)) {
            parent = document.createElement("tbody");
        } else if (/^<tbody/.test(html) || /^<thead/.test(html) || /^<caption/.test(html) || /^<tfoot/.test(html)) {
            parent = document.createElement("table");
        } else if ((/^<dt/.test(html) || /^<dd/.test(html))) {
            parent = document.createElement("dl");
        } else if (/^<li/.test(html)) {
            parent = document.createElement("ul");
        } else {
            parent = document.createElement('div'); //创建一个空的div  
        }
        this.html(parent, html);
        var resNodes = parent.childNodes;
        var res = [];
        for (let i = 0; i < resNodes.length; i++) {
            let node = resNodes[i];
            res.push(node);
            parent.removeChild(node);
        }
        if (res.length === 1) {
            return res[0];
        }
        return res;
    },
    requestAnimationFrame: function () {
        return requestAnimationFrame;
    },
    cancelAnimationFrame: function () {
        return cancelAnimationFrame;
    },
    /**
     * 获取可视窗口的大小
     * ***/
    getViewSize: function () {
        if (document.compatMode === "BackCompat") {
            return {
                width: document.body.clientWidth,
                height: document.body.clientHeight
            };
        } else {
            return {
                width: document.documentElement.clientWidth,
                height: document.documentElement.clientHeight
            };
        }
    },
    /**
     * 获取页面包括滚动条的大小
     * ***/
    getPageSize: function () {
        if (document.compatMode === "BackCompat") {
            return {
                width: Math.max(document.body.scrollWidth,
                    document.body.clientWidth),
                height: Math.max(document.body.scrollHeight,
                    document.body.clientHeight)
            };
        } else {
            return {
                width: Math.max(document.documentElement.scrollWidth,
                    document.documentElement.clientWidth),
                height: Math.max(document.documentElement.scrollHeight,
                    document.documentElement.clientHeight)
            };
        }
    },
    /*****
     * 设置dom loaded后的回调函数
     * *****/
    onDomLoaded: function (handler) {
        if (_isDomLoaded !== false) {
            handler.call(null, _isDomLoaded);
            return DomUtils;
        }
        _domLoadedHandlers.push(handler);
        return DomUtils;
    },
    /*****
     * 设置dom ready后的回调函数
     * *****/
    onDomReady: function (handler) {
        if (_isDomReady !== false) {
            handler.call(null, _isDomReady);
            return DomUtils;
        }
        _domReadyHandlers.push(handler);
        return DomUtils;
    },
    /***
     * 设置dom元素删除、新增的监听
     * handler = function(element,flag){}
     * element相关联的元素，flag=0表示删除，1表示新增
     ****/
    onDomNodeChanged: function (handler) {
        if (!this._domChangedListner) {
            this._domChangedListner = [];
        }
        handler.errorcout = 0;
        this._domChangedListner.push(handler);
    },
    /***
     * 解除dom变化监听
     * ***/
    offDomNodeChanged: function (handler) {
        if (this._domChangedListner) {
            var newEvents = [];
            for (let i = 0; i < this._domChangedListner.length; i++) {
                if (handler !== this._domChangedListner[i]) {
                    newEvents.push(this._domChangedListner[i]);
                }
            }
            this._domChangedListner = newEvents;
        }
    },
    invokeDomChangedEvents: function (element, flag) {
        if (this._domChangedListner) {
            var newEvents = [];
            for (let i = 0; i < this._domChangedListner.length; i++) {
                let fn = this._domChangedListner[i];
                try {
                    let ret = fn(element, flag);
                    if (typeof ret !== 'undefined' && !ret) {
                        fn.errorcout = 5;//清理这个回调
                    } else {
                        fn.errorcout = 0;
                    }
                } catch (x) {
                    fn.errorcout++;
                }
                if (fn.errorcout < 3) {
                    newEvents.push(fn);
                }
            }
            this._domChangedListner = newEvents;
        }
    }
};

function forachExecute(element, opr) {
    if (_isIterable(element)) {
        var retArr = [];
        _each(element, function (e) {
            let ret = DomUtils[opr](e);
            retArr.push(ret);
        });
        return retArr;
    }
    return undefined;
}

function _elementInsert(element, opr, html) {
    var isArr = _isIterable(element);
    if (isArr) {
        var res = [];
        _each(element, function (e) {
            res.push(DomUtils[opr](e, html));
        });
        return res.length === 1 ? res[0] : res;
    }
    return undefined;
}

function _getArrayFirstEl(element) {
    var isArr = _isIterable(element);
    if (isArr) {
        element = element[0];
    }
    return element;
}

/***
 * 读写scroll值
 * ***/
function _getSetScroll(element, prop, value) {
    var isArr = _isIterable(element);
    if (typeof value === "undefined") {
        if (isArr) {
            element = element[0];
        }
        if (element.tagName === "BODY" || element === document) {
            if (prop === "scrollTop") {
                return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
            }
            return document.documentElement.scrollLeft || window.pageXOffset || document.body.scrollLeft;
        }
        return element[prop];
    } else {
        if (isArr) {
            _each(element, function (e) {
                _getSetScroll(e, prop, value);
            });
        } else {
            element[prop] = value;
        }
    }
}

/******
 * 读写dom的高、宽
 * ********/
function getSetWH(element, attrName, val, exra) {
    if(!element || element.nodeType === 3){
        return typeof val === "undefined" ?  0 : DomUtils;
    }
    if (typeof val === "undefined") { //只有两个参数是读操作
        let v = DomUtils.domInfo(element)[attrName];
        let boxSize = DomUtils.css(element, "box-sizing");
        if (v !== 0 && exra) { //存在 exra则说明是 inner、outer
            if (attrName === "width") { /***innerWidth**/
                // if (boxSize === "content-box") {
                //     // let pl = DomUtils.css(element, "padding-left");
                //     // let pr = DomUtils.css(element, "padding-right");
                //     // v = v + pl + pr;                  
                // }
                if (exra === "outer" && boxSize !== "border-box") {//outerWidth：  border
                    let bl = DomUtils.css(element, "border-left-width");
                    let br = DomUtils.css(element, "border-right-width");
                    v = v + bl + br;
                }else if(exra === "inner"){
                    let isTd = element.nodeName === "TD";
                    let bl = DomUtils.css(element, "padding-left");
                    let br = DomUtils.css(element, "padding-right");
                    v = v - bl - br;
                    let l = $B.DomUtils.css(element, "border-right-width");
                    let r = $B.DomUtils.css(element, "border-left-width");
                    if(isTd){
                        l = l / 2;
                        r = r / 2;
                    }
                    v = v - l - r;
                }
            } else { //高度 
                //innerHeight               
                if (exra === "outer" && boxSize !== "border-box") {//outerHeight border
                    let bl = DomUtils.css(element, "border-top-width");
                    let br = DomUtils.css(element, "border-bottom-width");
                    v = v + bl + br;
                }else if(exra === "inner"){
                    let isTd = element.nodeName === "TD";
                    let t = $B.DomUtils.css(element, "border-top-width");
                    let b = $B.DomUtils.css(element, "border-bottom-width");
                    if(isTd){
                        t = t / 2;
                        b = b / 2;
                    }
                    v = v - t - b;
                    let bl = DomUtils.css(element, "padding-top");
                    let br = DomUtils.css(element, "padding-bottom");
                    v = v - bl - br;
                }
            }
        }
        return v;
    } else {//写操作
        if (_isNumeric(val)) {
            let strVal = val + "";
            if (/.+\d+$/.test(strVal)) {
                val = val + "px";
            }
        }
        let css = {};
        css[attrName] = val;
        DomUtils.css(element, css);
        return DomUtils;
    }
}
/***
 * DOMReady处理函数
 * ***/
function _onDOMReady(e) {
    DomUtils.body = DomUtils.findByTagName('body')[0];
    DomUtils.head = DomUtils.findByTagName('head')[0];
    var event = new EventArgs(e);
    _isDomReady = event;
    _each(_domReadyHandlers, function (fn) {
        fn.call(null, event);
    });
}
/**
 * DOMLoaded处理函数
 * ***/
function _onDOMLoaded(e) {
    var event = new EventArgs(e);
    _isDomLoaded = event;
    _each(_domLoadedHandlers, function (fn) {
        fn.call(null, event);
    });
}

//on load
if (window.onload !== null) {
    _domLoadedHandlers.push(window.onload);
}
window.onload = _onDOMLoaded;

//on ready
var readyFn;
if (addListener === 'addEventListener') {
    readyFn = function (e) {
        document[removeListener]('DOMContentLoaded', readyFn, false);//移除
        readyFn = undefined;
        _onDOMReady(e);
    };
    document[addListener]('DOMContentLoaded', readyFn, false);
} else {
    readyFn = function (e) {
        if (document.readyState === 'complete') {
            document[removeListener]('onreadystatechange', readyFn);//移除
            readyFn = undefined;
            _onDOMReady(e);
        }
    };
    document[addListener]('onreadystatechange', readyFn);
}
//创建dom变化监听，用于触发事件清理逻辑
function clearElementEvents(el) {
    if (el.nodeType === 1) {
        if (el.events) {
           
            DomUtils.offEvents(el);
        }
        if(el._clearAllFn){
            el._clearAllFn();
        }
        let _droplistid = $B.DomUtils.attribute(el, "_droplistid");
        if (_droplistid) { //移除对应的下拉dom           
            setTimeout(function () {
                let ele = document.getElementById(_droplistid);
                if (ele) {
                    if(ele._clearAllFn){
                        ele._clearAllFn();
                    }
                    $B.DomUtils.remove(ele);
                }
            }, 1);
        }
        var children = el.children;
        if (children) {
            for (let i = 0; i < children.length; i++) {
                clearElementEvents(children[i]);
            }
        }
    }

}

var onNodeRemovedFn = function (event) {
    event = event._e;
    if (event.target.nodeType === 1) {
        DomUtils.invokeDomChangedEvents(event.target, 0);
        if (event.target._isRetainEvent) { //避免被多次触发的场景           
            return;
        }
        event.target._isRetainEvent = true;
        var children = event.target.children;
        if (children) {
            let childs = Array.from(children);            
            _onNodeRemoveEventTimer = setTimeout(() => {
                for (let i = 0; i < childs.length; i++) {
                    clearElementEvents(childs[i]);
                }
            }, 8);
        }
        clearElementEvents(event.target);
        setTimeout(function () {
            event.target._isRetainEvent = undefined;
        }, 9);
    }
};
DomUtils.addListener(document, "DOMNodeRemoved", onNodeRemovedFn);
var DOMNodeInsertedFn = function (event) {
    DomUtils.invokeDomChangedEvents(event.target, 1);
};
DomUtils.addListener(document, "DOMNodeInserted", DOMNodeInsertedFn);
$B.DomUtils = DomUtils;
$B.Dom = DomUtils;
$B.onLoad = $B.DomUtils.onDomLoaded;

/*******动画*******/
function _isVelocityEl() {
    if (!window["Velocity"]) {
        return;
    }
    return window["Velocity"];
}
$B.createEl = function(html){
   return DomUtils.createEl(html);
}; 
/** Velocity 动画配置项的默认值 
 * props = {   
    duration: 400,         // 动画执行时间
    easing: "swing",       // 缓动效果
    queue: "",             // 队列
    begin: undefined,      // 动画开始时的回调函数
    progress: undefined,   // 动画执行中的回调函数（该函数会随着动画执行被不断触发）
    complete: undefined,   // 动画结束时的回调函数
    display: undefined,    // 动画结束时设置元素的 css display 属性
    visibility: undefined, // 动画结束时设置元素的 css visibility 属性
    loop: false,           // 循环
    delay: false,          // 延迟
    mobileHA: true         // 移动端硬件加速（默认开启）
}
 * **/
$B.velocity = function (el, css, props) {
    var fn = _isVelocityEl();
    if (fn) {
        fn(el, css, props);
    }
};
$B.animate = $B.velocity;
function exeAnimate(animate, args) {
    var fn = _isVelocityEl();
    if (fn) {
        let duration = 500;
        let completeFn, elArr, el;
        for (let i = 0; i < args.length; i++) {
            if (i === 0) {
                el = args[0];
            } else if (_isFunction(args[i])) {
                completeFn = args[i];
            } else if (_isNumeric(args[i])) {
                duration = parseInt(args[i]);
            }
        }
        elArr = el;
        if (!_isArray(el)) {
            elArr = [];
            elArr.push(el);
        }

        var opt = { duration: duration };
        for (let i = 0; i < elArr.length; i++) {
            if (completeFn && i === elArr.length - 1) {
                opt["complete"] = completeFn;
            }
            let display = undefined;
            if (animate === "slideDown" || animate === "show" || animate === "fadeIn") { //显示
                if (elArr[i]["_display"] && elArr[i]["_display"] !== "none") {
                    display = elArr[i]["_display"];
                } else {
                    let tagName = elArr[i].tagName;
                    if (tagName === "TABLE") {
                        display = "table";
                    } else if (tagName === "TBODY") {
                        display = "table-row-group";
                    } else if (tagName === "THEAD") {
                        display = "table-header-group";
                    } else if (tagName === "TFOOT") {
                        display = "table-footer-group";
                    } else if (tagName === "TR") {
                        display = "table-row";
                    } else if (tagName === "TD") {
                        display = "table-cell";
                    } else {
                        display = undefined;
                    }
                }
            } else { //隐藏记录display
                let srcdisplay = $B.DomUtils.css(elArr[i], "display");
                elArr[i]["_display"] = srcdisplay;
            }
            opt.display = display;
            fn(elArr[i], animate, opt);
        }
    }
}
$B.slideUp = function () {
    exeAnimate("slideUp", arguments);
};
$B.slideDown = function () {
    exeAnimate("slideDown", arguments);
};
$B.toggle = function(){
    let el = arguments[0];
    if(!el.style || el.style.display !== "none"){
        exeAnimate("slideUp", arguments);
    }else{
        exeAnimate("slideDown", arguments);
    }
};
$B.hide = function () {
    exeAnimate("fadeOut", arguments);
};
$B.show = function () {
    exeAnimate("fadeIn", arguments);
};
$B.fadeIn = function () {
    exeAnimate("fadeIn", arguments);
};
$B.fadeOut = function () {
    exeAnimate("fadeOut", arguments);
};
